home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
tc_menu.arc
/
TC-MENU.C
< prev
Wrap
Text File
|
1988-11-19
|
23KB
|
960 lines
/*
** TC-MENU.C
**
** Turbo C version of James Pinson's Lattice C program PULLDOWN.C
**
** I edited his program to suit my indentation style, cleaned up the
** code in a few places, and made adjustments for Turbo C.
**
** Compile with tcc -K tc-menu
** or in TC with O/C/C/Default char type...Unsigned
** Ignore the three compiler warnings.
**
** If you get snow on your monitor, type in tc-menu s to prevent
** the program from using direct screen writes.
**
** -- Scott Houck
*/
#include <stdio.h>
#include <ctype.h>
#include <dos.h>
#include <conio.h>
#include <mem.h>
#define BLACK 0 /* These are for color cards */
#define BLUE 1
#define GREEN 2
#define CYAN 3
#define RED 4
#define MAGENTA 5
#define BROWN 6
#define WHITE 7
#define L_BLUE 9 /* Light-blue foreground only */
#define L_GREEN 10 /* Light-green foreground only */
#define YELLOW 14
#define IWHITE 15 /* Intense-white foreground only */
#define UNDERLINE 1 /* These are for monochrome cards */
#define NORMAL 7
#define HI_INTEN 15
#define REVERSE 112
#define TRUE 1
#define FALSE 0
unsigned int page; /* extern decl. for functions */
unsigned int attribute;
unsigned int mon_type;
char wrt_meth = 'f';
#define NU_MAIN 5 /* number of main menu options */
#define NU_SUB 5 /* number of sub menu options */
int menu();
int pull_down();
void make_help();
void make_inst();
void mono_help();
void demo();
void help();
void gotoxy();
int wherexy();
void d_page();
void win_save();
int set_color();
void clear_window();
void box();
int what_mon();
void cls();
void make_window();
int cursor();
void print();
void dos_prt();
void fast_write();
int get_key();
struct menu_str /* change this if you need more options */
{
char *head;
char *body[NU_SUB];
void (*fun1)();
void (*fun2)();
void (*fun3)();
void (*fun4)();
void (*fun5)();
};
/*-----------*/
/* M A I N */
/*-----------*/
main(argc, argv)
int argc;
char **argv;
{
extern unsigned int page;
extern unsigned int attribute;
extern unsigned int mon_type;
int hi_attr, nor_attr;
static struct menu_str m_menu[NU_MAIN] =
{
" File ", /* The first menu option */
" Dir ", /* Menu sub options */
" Load ",
" Save ",
" dElete ",
" Path ",
demo, /* The functions each sub-option call */
demo,
demo, /* these all call the same fake function */
demo,
demo,
" fiNd ", /* The second menu option */
" All-words ",
" First-word ",
"\0",
"\0", /* space filler for unused option names */
"\0",
demo,
demo,
0, /* unused function pointer */
0,
0,
" Configure ", /* The third option */
" Modem ",
" Screen ",
" Printer ",
"\0",
"\0",
demo,
demo,
demo,
0,
0,
" Output ", /* The fourth menu option */
" Screen ",
" Printer ",
" Disk ",
" Modem ",
"\0",
demo,
demo,
demo,
demo,
0,
" Help ", /* The fifth option */
" Instant help (really works) ",
"\0",
"\0",
"\0",
"\0",
help,
0,
0,
0,
0,
};
/* was a slow write requested? */
if (tolower(*argv[1]) == 's')
wrt_meth = 's';
page = 0;
mon_type = what_mon();
if (mon_type == 1) /* Find out if you have a color card */
{
hi_attr = set_color(BLACK, CYAN); /* and set attributes accordingly */
nor_attr = set_color(WHITE, BLACK);
}
else
{
hi_attr = REVERSE;
nor_attr = NORMAL;
}
attribute = nor_attr;
cursor(0); /* hide cursor */
win_save('s');
cls();
if (mon_type == 1)
make_help();
make_inst(); /* Show instructions */
menu(m_menu, NU_MAIN, NU_SUB, hi_attr, nor_attr);
win_save('r'); /* restore text display*/
cursor(1); /* restore cursor */
}
/*-----------*/
/* M E N U */
/*-----------*/
int menu(m_menu, nu_main, nu_sub, hi_attr, nor_attr)
struct menu_str m_menu[];
int nu_main, nu_sub, hi_attr, nor_attr;
{
extern unsigned int page;
extern unsigned int attribute;
extern unsigned int mon_type;
int i, j, cur_x, cur_y, cur_opt, found, expert = 1;
char ch, ext, ltr;
ch = ' ';
ext = ' ';
cur_opt = 0;
found = 0;
if (mon_type == 1)
attribute = set_color(YELLOW, BLACK);
else
attribute = nor_attr;
make_window(1, 1, 78, 1, 1);
for (;;) /* endless loop */
{
for (i = 0; i < nu_main; i++)
{
j = 0;
while (ltr = m_menu[i].head[j++])
{
if (ch == ltr && ch != ' ')
{
found = TRUE;
cur_opt = i;
}
}
}
if (ch == 13)
{
found = TRUE;
expert = FALSE;
}
ch = ' ';
cur_x = 2;
cur_y = 2;
for (i = 0; i < nu_main; i++)
{
if (i == cur_opt)
attribute = hi_attr;
else
attribute= nor_attr;
print(cur_x, cur_y, m_menu[i].head);
cur_x += strlen(m_menu[i].head) + 3;
}
if (!expert)
found = TRUE;
if (found)
{
ext = pull_down(m_menu, nu_sub, cur_opt); /* pull-down options */
if (ext == 27)
expert = TRUE;
if (ext == 'r' || ext == 'l')
expert = FALSE;
if (ext == 'r')
++cur_opt;
if (ext == 'l')
--cur_opt;
ch = ' ';
ext = ' ';
}
if (!found)
{
ch = ' ';
get_key(&ch, &ext);
ch = toupper(ch);
}
if (ch == 27)
return;
if (ext == 'r' || ext == 'l')
expert = 0;
if (ext == 'r')
++cur_opt;
if (ext == 'l')
--cur_opt;
if (cur_opt >= nu_main)
cur_opt = 0;
if (cur_opt < 0)
cur_opt = nu_main - 1;
ext = ' ';
found = 0;
} /* end for (;;) */
}
/*---------------------*/
/* P U L L _ D O W N */
/*---------------------*/
int pull_down(m_menu, nu_sub, position)
struct menu_str m_menu[];
int position;
{
extern unsigned int page;
extern unsigned int attribute;
char ch = ' ', ltr;
int ext = ' ', hi_attr, nor_attr;
int i, j, tx, ty, start, width, nu_opt, cur_opt = 0, found = FALSE;
nu_opt = nu_sub;
/* nu_sub = number of possible pull-down options */
/* find out how many are in use */
for (i = 0; i < nu_opt; i++)
{
if (m_menu[position].body[i][0] == '\0')
{
nu_opt = i;
break;
}
}
if (mon_type == 1)
{
hi_attr = set_color(BLACK, CYAN);
nor_attr = set_color(WHITE, BLACK);
}
else
{
hi_attr = REVERSE;
nor_attr = NORMAL;
}
attribute = nor_attr;
start = 2; /* Figure where to draw pull-down box */
/* 2 is column to start 1st box */
/* Add up length of menu heads */
for (i = 0; i < position; i++)
start += strlen(m_menu[i].head) + 3;
width = 0; /* figure max length of window */
for (i = 0; i < nu_opt; i++)
if (strlen(m_menu[position].body[i]) > width)
width = strlen(m_menu[position].body[i]);
/* move box to left if it will spill off right side */
if (start + width + 1 > 80)
start = 80 - width - 2;
win_save('s');
if (mon_type == 1)
attribute = set_color(YELLOW, BLACK);
make_window(start++, 3, width, nu_opt, 0); /*make a window */
attribute = nor_attr;
tx = start; /* reposition for writing */
ty = 4;
for (;;)
{
for (i = 0; i < nu_opt; i++)
{
if (i == cur_opt)
attribute = hi_attr;
else
attribute = nor_attr;
print(tx, ty++, m_menu[position].body[i]);
}
attribute = nor_attr;
if (found)
{
win_save('r'); /* remove box */
/* If you want more than 5 menu options */
/* change this next switch statement */
switch(cur_opt) /* call function */
{
case 0: (*m_menu[position].fun1)(); break;
case 1: (*m_menu[position].fun2)(); break;
case 2: (*m_menu[position].fun3)(); break;
case 3: (*m_menu[position].fun4)(); break;
case 4: (*m_menu[position].fun5)(); break;
}
/* found = FALSE; */
if (kbhit())
getch(); /* make sure keyboard buffer is clear */
return(' ');
}
tx = start;
ty = 4;
get_key(&ch, &ext); /* get a character */
ch = toupper(ch);
if (ext == 'd')
++cur_opt;
if (ext == 'u')
--cur_opt;
if (cur_opt >= nu_opt)
cur_opt = 0;
if (cur_opt < 0)
cur_opt = nu_opt - 1;
if (ch == 13)
found = TRUE;
for (i = 0; i < nu_opt; i++) /* does it match an option? */
{
j = 0;
while (ltr = m_menu[position].body[i][j++])
{
if (ch == ltr)
{
cur_opt = i;
found = TRUE;
}
}
}
if (ext == 'l'|| ext == 'r')
break;
if (ch == 27) /* EXIT IF ESCAPE KEY */
{
ext = ch;
break;
}
ext = ' ';
ch = ' ';
} /* end for (;;) */
win_save('r');
return (ext);
}
/*---------------------*/
/* M A K E _ H E L P */
/*---------------------*/
void make_help()
{
extern unsigned int page, attribute;
page = 1;
print( 1, 1, "Hello - This is a sample of an instant help screen.");
print(10, 5, "This screen was printed to the second page of graphics");
print(10, 7, "while you were looking at the main menu.");
print(10, 9, "This help screen can be left undisturbed");
print(10, 11, "and redisplayed at any time.");
print( 1, 20, "Please touch any key to return to the main menu.");
page = 0;
}
/*---------------------*/
/* M A K E _ I N S T */
/*---------------------*/
void make_inst()
{
extern unsigned int attribute;
if (mon_type == 1)
attribute = set_color(GREEN, BLACK);
else
attribute = NORMAL;
print( 1, 4, "INSTRUCTIONS:");
print( 1, 6, "EXPERT MODE: Select by touching the key which represents each option.");
print(15, 7, "(the capital letter)");
print( 1, 10, "ASSIST MODE: Pull-down menu by touching 'enter' or a cursor key.");
print(14, 11, "Select by highlighting with cursor keys- then touch return");
print(14, 13, "Return to Expert mode by touching 'escape'");
print( 1, 15, "EXIT: Touch 'Escape' while in expert mode.");
}
/*---------------------*/
/* M O N O _ H E L P */
/*---------------------*/
void mono_help()
{
attribute = NORMAL;
win_save('s');
clear_window(1, 4, 80, 21);
print(1, 7, "This is a demonstration of a help screen.");
print(1, 9, "This text was written by means of direct memory address.");
print(1, 10, "The original screen has been saved and will be restored ");
print(1, 11, "when you exit this 'help' screen.");
print(1, 14, "Please touch any key to continue.");
getch();
win_save('r');
}
/*-----------*/
/* D E M O */
/*-----------*/
void demo()
{
win_save('s');
make_window(20, 10, 40, 5, 1);
print(21, 11, "Put your favorite routine here ");
print(21, 14, "touch any key to return to menu");
getch();
win_save('r');
}
/*-----------*/
/* H E L P */
/*-----------*/
void help()
{
if (mon_type == 1) /* If color card flip page to */
{
page = 1; /* Show text else write to current screen */
d_page();
getch();
page = 0;
d_page();
}
else
mono_help();
}
/* Screen Function Library */
/*
** Declare the extern variables page, attribute, and
** mon_type (monitor type) in your main program.
*/
/*---------------*/
/* G O T O X Y */
/*---------------*/
void gotoxy(x, y) /* Puts cursor at x,y position on selected page */
unsigned int x, y; /* 1,1 is upper left corner */
{
extern unsigned int page;
union REGS regist;
if (x < 1 || x > 80)
return;
if (y < 1 || y > 25)
return;
--x;
--y; /* BIOS starts coordinates at 0,0 */
regist.h.ah = 0x02;
regist.x.dx = (y << 8) | x;
regist.h.bh = page;
int86(0x10, ®ist, ®ist);
}
/*-----------------*/
/* W H E R E X Y */
/*-----------------*/
int wherexy(x, y) /* Returns the x,y position of cursor */
int *x, *y;
{
extern unsigned int page;
union REGS regist;
regist.h.ah = 0x03;
regist.h.bh = page;
int86(0x10, ®ist, ®ist);
*x = regist.h.dl + 1;
*y = regist.h.dh + 1;
}
/*---------------*/
/* D _ P A G E */
/*---------------*/
/* Displays the page indicated by extern var page */
/* Use only with color card */
void d_page()
{
extern unsigned int page;
union REGS regist;
regist.h.ah = 0x05;
regist.h.al = page;
int86(0x10, ®ist,®ist);
}
/*-------------------*/
/* W I N _ S A V E */
/*-------------------*/
void win_save(action) /* Saves or restores primary */
int action; /* display screen. */
{ /* (page 0 for color display) */
extern unsigned int page; /* 's' = save */
extern unsigned int mon_type; /* 'r' = restore */
int position; /* Saves cursor position too */
static int ptr; /* May make snow on CGA */
static struct
{
int x;
int y;
unsigned int buffer[4000];
}
window[2];
if (mon_type == 1)
position = 0xB800; /* Color card */
else
position = 0xB000; /* Monochrome */
if (action == 's') /* save */
{
if (ptr > 1)
{
ptr = 2;
return;
}
/*
** Note: I used movedata because the peek function is specific
** to Lattice C.
**
** peek(position, 0x00, &window[ptr].buffer, 4000);
**
** Also see poke below.
*/
/* save screen */
movedata(position, 0, _DS, (int)&window[ptr].buffer, 4000);
/* save cursor location */
wherexy(&window[ptr].x, &window[ptr].y);
ptr++;
}
if (action == 'r') /* restore */
{
if (ptr < 1)
{
ptr = 0;
return;
}
--ptr;
/* poke(position, 0, &window[ptr].buffer, 4000); */
/* restore screen */
movedata(_DS, (int)&window[ptr].buffer, position, 0, 4000);
/* restore cursor location */
gotoxy(window[ptr].x, window[ptr].y);
}
}
/*---------------------*/
/* S E T _ C O L O R */
/*---------------------*/
/* Call with foreground and background colors. Returns attribute. */
int set_color(foreground, background)
int foreground,background;
{
return (background << 4 | foreground);
}
/*---------------------------*/
/* C L E A R _ W I N D O W */
/*---------------------------*/
void clear_window(x, y, width, height) /* Call with x,y of upper left */
unsigned int x, y, width, height; /* corner of window area. */
{ /* Clears down and to right */
extern unsigned int page; /* for width and height. */
extern unsigned int attribute; /* Cleared with active attribute */
union REGS regist; /* Use on displayed page only! */
regist.x.ax = 0x0600;
regist.h.ch = --y;
regist.h.cl = --x;
regist.x.dx = (y + height - 1) << 8 | x + width - 1;
regist.h.bh = attribute;
int86(0x10, ®ist, ®ist);
}
/*---------*/
/* B O X */
/*---------*/
void box(x, y, width, height, type) /* type 0 = pull-down box */
int x, y, width, height, type; /* type 1 = regular box */
{
int i, u_right, u_left;
char string[82];
if (type == 0) /* following sets corners */
{
u_left = '\xC2';
u_right = '\xC2';
}
else if (type == 1)
{
u_left = '\xDA';
u_right = '\xBF';
}
string[0] = u_left;
for (i = 1; i <= width; string[i++] = '\xC4');
string[i++] = u_right;
string[i] = '\0';
print(x, y++, string);
for (i = 0; i < height; i++)
{
print(x, y, "\xB3");
print(x + width + 1, y++, "\xB3");
}
string[0]='\xC0';
for(i = 1; i <= width; string[i++] = '\xC4');
string[i++] = '\xD9';
string[i] = '\0';
print(x, y++, string);
}
/*-------------------*/
/* W H A T _ M O N */
/*-------------------*/
int what_mon() /* Returns a 1 if color card present, 0 if monochrome */
{
return (peekb(0x0040, 0x0049) != 7);
}
/*---------*/
/* C L S */
/*---------*/
void cls() /* Same as DOS cls */
{
clear_window(1, 1, 80, 25);
gotoxy(1, 1);
}
/*-------------------------*/
/* M A K E _ W I N D O W */
/*-------------------------*/
void make_window(x, y, width, height, type) /* Draws and clears a box */
unsigned int x, y, width, height, type;
{
box(x++, y++, width, height, type); /* Draw box */
clear_window(x, y, width, height); /* Clear interior */
}
/*---------------*/
/* C U R S O R */
/*---------------*/
int cursor(size) /* Sets cursor size */
int size; /* 0 = no cursor, 1 = normal, 2 = big cursor */
{
union REGS regist;
regist.h.ah = 0x01;
if (mon_type == 1 ) /* color */
{
if (size == 0)
regist.x.cx = 0x0F0F;
else if (size == 1)
regist.x.cx = 0x0607;
else if (size == 2)
regist.x.cx = 0x0107;
}
else /* monochrome */
{
if (size == 0)
regist.x.cx = 0x0F0F;
else if (size == 1)
regist.x.cx = 0x0C0D;
else if (size == 2)
regist.x.cx = 0x010D;
}
int86(0x10, ®ist, ®ist);
}
/*-------------*/
/* P R I N T */
/*-------------*/
void print(x, y, str) /* A switcher - routes to fast_write */
unsigned int x, y; /* or to dos_prt depending on argv */
char *str; /* passed to program and stored in */
{ /* extern char wr_meth */
extern char wrt_meth;
if (wrt_meth == 'f') /* Fast (direct poking) */
fast_write(x, y, str);
else if (wrt_meth == 's') /* Slow (DOS method) */
{
gotoxy(x, y);
dos_prt(str);
}
}
/*-----------------*/ /* Asks DOS to write a string with attribute */
/* D O S _ P R T */ /* defined. an alternative to fast write in */
/*-----------------*/ /* that it is "well behaved" (goes through DOS) */
/* Specify page and set cursor position before */
void dos_prt(str) /* calling */
char *str;
{
extern unsigned int page, attribute;
unsigned int x, y;
union REGS regist;
wherexy(&x, &y);
while (*str)
{
if (x > 80)
{
x = 1;
++y;
}
if (y > 25)
break;
gotoxy(x++, y);
regist.x.bx = (page << 8 | attribute);
regist.x.cx = 1;
regist.x.ax = 0x0900 | *str++;
int86(0x10, ®ist, ®ist);
}
gotoxy(x, y); /* put cursor at end of string */
}
/*-----------------------*/
/* F A S T _ W R I T E */
/*-----------------------*/
void fast_write(x, y, string) /* Directly pokes string at x,y position */
int x, y; /* Uses attribute and page. */
char *string; /* May cause snow on some graphic cards */
{
extern unsigned int page;
extern unsigned int attribute;
extern unsigned int mon_type; /* Monitor type */
int position, offset, orig;
if (page <= 3 && page >= 0)
offset = 4000 * page + 96 * page;
orig = offset;
offset += (y-1) * 160 + 2 * (x-1);
if (mon_type == 0)
position = 0xB000;
else
position = 0xB800;
while (*string)
{
pokeb(position, offset, *string++); /* Poke character */
pokeb(position, offset+1, (char)attribute); /* Poke attribute */
offset += 2;
}
offset -= orig; /* Figure where I am */
x = (offset % 160) / 2 + 1;
y = offset / 160 + 1; /* and move cursor */
gotoxy(x, y);
}
/*-----------------*/
/* G E T _ K E Y */
/*-----------------*/
int get_key(ch, ext) /* Read a char */
char *ch; /* Return character in ch */
int *ext; /* If it is a function key */
{ /* return following in ext */
*ch = getch(); /* up-arrow = 'u' */
if (!*ch) /* down-arrow = 'd' */
{ /* right-arrow = 'r' */
*ext = getch(); /* left-arrow = 'l' */
switch (*ext)
{
case 'H': *ext = 'u'; break; /* up */
case 'P': *ext = 'd'; break; /* down */
case 'M': *ext = 'r'; break; /* right */
case 'K': *ext = 'l'; break; /* left */
case 'G': *ext = 'h'; break; /* home */
case 'O': *ext = 'e'; break; /* end */
case 'R': *ext = 'I'; break; /* insert */
case 'S': *ext = 'D'; break; /* delete */
}
}
}